package ThreadSafety;

import java.util.Scanner;

class Counter {
    volatile public int size;   //加上volatile,就是告诉jvm这个变量是会变的,必须每次都要读取size的值(volatile只能修饰变量)
}
public class MemoryVisibility {
    /**  内存可见性问题:一个线程对一个变量进行读取操作,同时另一个线程对这个变量就行修改,
     *       由于长时间的读取同一个值,此时读到的值(寄存器的值),不一定是修改后的值,这个线程没有感知到变量的变化
     *    归根结底,是jvm在多线程环境下,优化代码是产生误判,也就是产生bug了
     */
    public static void main(String[] args) {
        Counter counter = new Counter();
        Thread t1 = new Thread(() -> {
            /*这个循环执行速度很快,一秒钟执行上百万次以上,循环这么多次在t2真正修改变量之前
            * 读取到的变量的值都是一样的,另一方面读取操作和比较操作相比,速度相差很多,读取一次能比较很多次
            * 由于读取执行太慢,再加上每次读取的结果都一样,jvm就判定没有人修改变量的值(此时就会代码优化),就只读取一次
            */
            while (counter.size == 0) {
                //加了sleep之后,控制了循环的速度,此时不加volatile 代码也正确
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
            System.out.println("循环结束!!!");
        });
        Thread t2 = new Thread(()->{
            Scanner scanner = new Scanner(System.in);
            System.out.print("请输入一个数 : ");
            counter.size = scanner.nextInt();
        });
        t1.start();
        t2.start();
    }
}
